#include "BasicBlock.hpp"
#include "Constant.hpp"
#include "Function.hpp"
#include "IRBuilder.hpp"
#include "Module.hpp"
#include "Type.hpp"

#include <iostream>
#include <memory>

// 定义一个从常数值获取/创建 ConstantInt 类实例化的宏，方便多次调用
#define CONST_INT(num) \
    ConstantInt::get(num, module)

// 定义一个从常数值获取/创建 ConstantFP 类实例化的宏，方便多次调用
#define CONST_FP(num) \
    ConstantFP::get(num, module)

int main() {
    auto module = new Module();
    auto builder = new IRBuilder(nullptr, module);
    Type *Int32Type = module->get_int32_type();

    // callFun 函数
    std::vector<Type *> argsType(1, Int32Type);
    auto callFunTy = FunctionType::get(Int32Type, argsType);
    auto callFun = Function::create(callFunTy, "callFun", module);
    auto callFunBB = BasicBlock::create(module, "entry", callFun);
    builder->set_insert_point(callFunBB);

    // 为参数 a 分配空间
    auto aAlloca = builder->create_alloca(Int32Type);
    std::vector<Value *> args;
    for (auto &arg : callFun->get_args()) {
        args.push_back(&arg);
    }
    builder->create_store(args[0], aAlloca);

    // a = a + 1
    auto aLoad = builder->create_load(aAlloca);
    auto add = builder->create_iadd(aLoad, CONST_INT(1));
    builder->create_store(add, aAlloca);

    // return 2 * a
    aLoad = builder->create_load(aAlloca);
    auto mul = builder->create_imul(CONST_INT(2), aLoad);
    builder->create_ret(mul);

    // main 函数
    auto mainFun = Function::create(FunctionType::get(Int32Type, {}), "main", module);
    auto mainBB = BasicBlock::create(module, "entry", mainFun);
    builder->set_insert_point(mainBB);

    // 为函数返回值分配空间
    auto retAlloca = builder->create_alloca(Int32Type);
    // main 函数默认 ret 0
    builder->create_store(CONST_INT(0), retAlloca);

    // 调用 callFun(90)
    auto call = builder->create_call(callFun, {CONST_INT(90)});
    builder->create_ret(call);

    // 输出 module 中的所有 IR 指令
    std::cout << module->print();
    delete module;
    delete builder;
    return 0;
}
